package resolver

// This file will be automatically regenerated based on the schema, any resolver implementations
// will be copied through when generating and any unknown code will be moved to the end.

import (
	"context"
	"errors"
	"fmt"
	"strconv"

	"mall/service/backend/rpc/backendclient"
	"mall/service/blog/rpc/blogclient"
	"mall/service/wpgql/api/internal/graph/generated"
	"mall/service/wpgql/api/internal/graph/helper"
	"mall/service/wpgql/api/internal/graph/model"
	"mall/service/wpgql/api/internal/graph/util"
)

const blogPostSingleError = "could not get blog post"
const blogPostListError = "could not list blog posts"

func (r *mutationResolver) CreatePost(ctx context.Context, input model.CreatePostInput) (*model.CreatePostPayload, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *mutationResolver) DeletePost(ctx context.Context, input model.DeletePostInput) (*model.DeletePostPayload, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *mutationResolver) UpdatePost(ctx context.Context, input model.UpdatePostInput) (*model.UpdatePostPayload, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *postResolver) Categories(
	ctx context.Context,
	obj *model.Post,
	first *int,
	last *int,
	after *string,
	before *string,
	where *model.PostToCategoryConnectionWhereArgs,
) (*model.PostToCategoryConnection, error) {
	if where == nil {
		return obj.Categories, nil
	}

	return &model.PostToCategoryConnection{}, nil
}

func (r *postResolver) Comments(
	ctx context.Context,
	obj *model.Post,
	first *int,
	last *int,
	after *string,
	before *string,
	where *model.PostToCommentConnectionWhereArgs,
) (*model.PostToCommentConnection, error) {
	if where == nil {
		return obj.Comments, nil
	}

	return &model.PostToCommentConnection{}, nil
}

func (r *postResolver) Content(ctx context.Context, obj *model.Post, format *model.PostObjectFieldFormatEnum) (*string, error) {
	var content string
	if obj != nil {
		if obj.Content != nil {
			content = *obj.Content
		}
	}

	return &content, nil
}

func (r *postResolver) EnqueuedScripts(ctx context.Context, obj *model.Post, first *int, last *int, after *string, before *string) (*model.ContentNodeToEnqueuedScriptConnection, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *postResolver) EnqueuedStylesheets(ctx context.Context, obj *model.Post, first *int, last *int, after *string, before *string) (*model.ContentNodeToEnqueuedStylesheetConnection, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *postResolver) Excerpt(ctx context.Context, obj *model.Post, format *model.PostObjectFieldFormatEnum) (*string, error) {
	var excerpt string
	if obj != nil {
		if obj.Excerpt != nil {
			excerpt = *obj.Excerpt
		}
	}

	return &excerpt, nil
}

func (r *postResolver) PostFormats(ctx context.Context, obj *model.Post, first *int, last *int, after *string, before *string, where *model.PostToPostFormatConnectionWhereArgs) (*model.PostToPostFormatConnection, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *postResolver) Revisions(ctx context.Context, obj *model.Post, first *int, last *int, after *string, before *string, where *model.PostToRevisionConnectionWhereArgs) (*model.PostToRevisionConnection, error) {
	panic(fmt.Errorf("not implemented"))
}

func (r *postResolver) Tags(
	ctx context.Context,
	obj *model.Post,
	first *int,
	last *int,
	after *string,
	before *string,
	where *model.PostToTagConnectionWhereArgs,
) (*model.PostToTagConnection, error) {
	if where == nil {
		return obj.Tags, nil
	}

	return &model.PostToTagConnection{}, nil
}

func (r *postResolver) Terms(
	ctx context.Context,
	obj *model.Post,
	first *int,
	last *int,
	after *string,
	before *string,
	where *model.PostToTermNodeConnectionWhereArgs,
) (*model.PostToTermNodeConnection, error) {
	if where == nil {
		return obj.Terms, nil
	}

	return &model.PostToTermNodeConnection{}, nil
}

func (r *postResolver) Title(ctx context.Context, obj *model.Post, format *model.PostObjectFieldFormatEnum) (*string, error) {
	var title string
	if obj != nil {
		if obj.Title != nil {
			title = *obj.Title
		}
	}

	return &title, nil
}

func (r *queryResolver) Post(
	ctx context.Context,
	id string,
	idType *model.PostIDType,
	asPreview *bool,
) (*model.Post, error) {
	req := &blogclient.PostDetailRequest{}

	var preview bool
	if asPreview != nil {
		preview = *asPreview
	}
	req.AsPreview = preview

	preload, eagerLoad := helper.GetBlogPostPreloads(ctx)
	if preload != "" {
		req.Preload = preload
	}
	if eagerLoad != "" {
		req.EagerLoad = eagerLoad
	}
	filter := helper.GetBlogPostFilter(id, idType)
	if filter != "" {
		req.Filter = filter
	}

	res, err := r.svcCtx.BlogRpc.PostDetail(ctx, req)
	if err != nil {
		return nil, errors.New(blogPostSingleError)
	}

	if res.AuthorId > 0 {
		userList, err := r.svcCtx.BackendRpc.UserList(ctx, &backendclient.UserListRequest{
			UserIds: strconv.FormatInt(res.AuthorId, 10),
		})
		if err != nil {
			return nil, err
		}
		if userList.Total > 0 {
			user := userList.List[0]
			res.Author = &blogclient.BlogAuthor{
				Id:   user.Id,
				Name: user.Name,
				Url:  user.Avatar,
			}
		}
	}

	return helper.BlogPostToGraphQL(res), nil
}

func emptyRootQueryToPostConnection() *model.RootQueryToPostConnection {
	return &model.RootQueryToPostConnection{
		Edges:    []*model.RootQueryToPostConnectionEdge{},
		Nodes:    []*model.Post{},
		PageInfo: &model.WPPageInfo{},
	}
}

func (r *queryResolver) Posts(
	ctx context.Context,
	first *int,
	last *int,
	after *string,
	before *string,
	where *model.RootQueryToPostConnectionWhereArgs,
) (*model.RootQueryToPostConnection, error) {
	req := &blogclient.PostListReq{}

	preload, eagerLoad := helper.GetBlogPostNodesPreloads(ctx)
	if preload != "" {
		req.Preload = preload
	}
	if eagerLoad != "" {
		req.EagerLoad = eagerLoad
	}

	pagination := util.NewPagination(first, last, after, before,
		r.svcCtx.Config.Query.DefaultAmount, r.svcCtx.Config.Query.MaxAmount)

	var sorter []*model.PostObjectsConnectionOrderbyInput
	if where != nil {
		sorter = where.Orderby
	}
	sorterMap := helper.GetBlogPostConnectionSorterMap(pagination, sorter)
	var reverse bool
	if sorterMap != nil {
		for k, v := range sorterMap {
			switch k {
			case "offset":
				if i, err := strconv.ParseInt(v, 10, 32); err == nil {
					req.Offset = int32(i)
				}
			case "limit":
				if i, err := strconv.ParseInt(v, 10, 32); err == nil {
					req.Limit = int32(i)
				}
			case "sorter":
				req.Sorter = v
			case "reverse":
				if v == "1" {
					reverse = true
				}
			}
		}
	}

	filterMap := helper.GetBlogPostConnectionFilterMap(where)
	if filterMap != nil {
		for k, v := range filterMap {
			switch k {
			case "search":
				req.Search = v
			case "filter":
				req.Filter = v
			case "preFilterEntity":
				req.PreFilterEntity = v
			case "preFilter":
				req.PreFilter = v
			}
		}
	}

	res, err := r.svcCtx.BlogRpc.PostList(ctx, req)
	if err != nil {
		return &model.RootQueryToPostConnection{}, errors.New(blogPostListError)
	}

	if len(res.Data) > 0 {
		var entries []*model.Post
		for _, entry := range res.Data {
			entries = append(entries, helper.BlogPostToGraphQL(entry))
		}
		connection := helper.GetRootQueryToPostConnection(entries,
			res.HasNextPage > 0, res.HasPreviousPage > 0, req.Offset, reverse)
		return connection, nil
	}

	return emptyRootQueryToPostConnection(), nil
}

// Post returns generated.PostResolver implementation.
func (r *Resolver) Post() generated.PostResolver { return &postResolver{r} }

type postResolver struct{ *Resolver }
